/*
 * @Author: your name
 * @Date: 2021-05-26 16:53:55
 * @LastEditTime: 2021-05-26 16:54:09
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /xiangpan-admin/src/use/useObj.ts
 */
import { useState, useRef, Dispatch } from 'react';
import produce, { Draft } from 'immer';

type SetStateAction<S> = S | ((prevState: S) => any);

function isFunction(val: unknown): val is Function {
  return typeof val === 'function';
}

export default function useObj<S extends { [key: string]: any }>(
  defaultState: S | (() => S),
) {
  const [obj, setObj] = useState<S>(defaultState);
  const cb = useRef<(nextState: S) => void>();

  const setState = (
    // value: Partial<S> | Dispatch<SetStateAction<S>>,
    value: Partial<S> | ((prevState: Draft<S>) => any),
    callback?: (nextState: S) => void,
  ) => {
    cb.current = callback;
    setObj((prev) => {
      const nextState = produce(prev, (draft) => {
        if (isFunction(value)) {
          value(draft);
        } else {
          Object.assign(draft, value);
        }
        // const newState = isFunction(value) ? value(_.cloneDeep(prev)) : value;
        // Object.assign(draft, newState);
      });
      return nextState;
    });
    callback &&
      setObj((prev) => {
        callback(prev);
        return prev;
      });
  };

  return [obj, setState] as const;
}
